﻿using Emgu.CV;
using FinalYear.Helpers;
using FinalYear.iNavigate.Classes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms.Integration;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Telerik.Windows.Controls;

namespace FinalYear.iNavigate
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Navigator bottomnavigator;
        private System.Windows.Media.Brush collisionButtonBackground;
        private SerialManager manager;
        private string selectedItem;
        private DispatcherTimer timer;
        private Navigator topNavigator;
        private BackgroundWorker workerProcess;

        public MainWindow()
        {
            ElementHost.EnableModelessKeyboardInterop(this);
            StyleManager.ApplicationTheme = new Windows8Theme();
            this.manager = new SerialManager();
            this.manager.OpenPort();
            InitializeComponent();
            this.collisionButtonBackground = this.btnCollision.Background;
            //this.iNavigateProperties.inputProperties.Item = new Navigator();
            //Navigator curr = (Navigator)this.iNavigateProperties.inputProperties.Item;
            //curr.Changed += PropertyChanged;
            this.bottomnavigator = new Navigator(Device.CAMERALOW, this.manager);
            this.topNavigator = new Navigator(Device.CAMERAHI, this.manager);

            this.iNavigateProperties.inputProperties.Item = this.bottomnavigator;

            List<Device> enumDevices = Enum.GetValues(typeof(Device)).Cast<Device>().ToList();
            for (int i = 0; i < enumDevices.Count; i++)
            {
                RadComboBoxItem item = new RadComboBoxItem();
                item.Content = enumDevices[i];
                this.rdchkbxAddons.Items.Add(item);
            }

            this.rdchkbxCameraFeed.Items.Add(Device.CAMERALOW);
            this.rdchkbxCameraFeed.Items.Add(Device.CAMERAHI);
            this.rdchkbxCameraFeed.SelectedIndex = 0;
        }

        [DllImport("gdi32")]
        private static extern int DeleteObject(IntPtr o);

        private static BitmapSource ToBitmapSource(IImage image)
        {
            using (Bitmap source = image.Bitmap)
            {
                IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap

                BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    ptr,
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

                DeleteObject(ptr); //release the HBitmap
                return bs;
            }
        }

        private void inputProperties_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            throw new NotImplementedException();
        }

        private void PropertyChanged(object sender, EventArgs e)
        {
            Navigator senderObj = (Navigator)sender;

            // check if the current feed is either low or high
            string selectedItem = this.rdchkbxCameraFeed.SelectionBoxItem.ToString();
            Device currentCameraFeed = EnumUtil.ParseEnum<Device>(selectedItem);

            if (currentCameraFeed == Device.CAMERALOW)
            {
                this.bottomnavigator.UseSonar = senderObj.UseSonar;
                this.bottomnavigator.MaxFeatureCount = senderObj.MaxFeatureCount;
                this.bottomnavigator.MinimumCollisionMagnitude = senderObj.MinimumCollisionMagnitude;
            }
            else
            {
                this.topNavigator.MaxFeatureCount = senderObj.MaxFeatureCount;
                this.topNavigator.MinimumCollisionMagnitude = senderObj.MinimumCollisionMagnitude;
            }
        }

        private void rdbtnDiagnostic_Click(object sender, RoutedEventArgs e)
        {
            this.selectedItem = this.rdchkbxAddons.SelectionBoxItem.ToString();
            this.rdbsyIndicator.IsBusy = true;
            this.workerProcess = new BackgroundWorker();
            this.workerProcess.DoWork += workerProcess_DoWork;
            this.workerProcess.RunWorkerCompleted += workerProcess_RunWorkerCompleted;
            this.workerProcess.RunWorkerAsync();
        }

        private void rdchkbxAddons_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //Device currentCameraFeed = EnumUtil.ParseEnum<Device>(selectedItem);

            //if (currentCameraFeed == Device.CAMERALOW)
            //{
            //    this.iNavigateProperties.inputProperties.Item = this.bottomnavigator;
            //}
            //else
            //{
            //    this.iNavigateProperties.inputProperties.Item = this.topNavigator;
            //}
        }

        private void rdchkbxCameraFeed_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            string selectedItem = this.rdchkbxCameraFeed.SelectionBoxItem.ToString();
            EnumUtil.ParseEnum<Device>(selectedItem);

            Device currentCameraFeed = EnumUtil.ParseEnum<Device>(selectedItem);

            if (currentCameraFeed == Device.CAMERALOW)
            {
                this.iNavigateProperties.inputProperties.Item = this.bottomnavigator;
            }
            else
            {
                this.iNavigateProperties.inputProperties.Item = this.topNavigator;
            }
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            bottomnavigator.ProcessFrame();
            topNavigator.ProcessFrame();

            string selectedItem = this.rdchkbxCameraFeed.SelectionBoxItem.ToString();
            Device selectedCamera = EnumUtil.ParseEnum<Device>(selectedItem);

            if (selectedCamera == Device.CAMERALOW)
            {
                if (bottomnavigator.PreviousGrayImage != null)
                {
                    //canvas = new Canvas();
                    canvas.Background = new ImageBrush(ToBitmapSource(this.bottomnavigator.FlowImage));
                    this.UpdateTextBoxValues(bottomnavigator);
                }
            }
            else
            {
                if (topNavigator.PreviousGrayImage != null)
                {
                    // canvas = new Canvas();
                    canvas.Background = new ImageBrush(ToBitmapSource(this.topNavigator.FlowImage));
                    this.UpdateTextBoxValues(topNavigator);
                }
            }
        }

        private void UpdateTextBoxValues(Navigator currentNavigationOption)
        {
            this.txtbxFrameRate.Text = currentNavigationOption.FrameRate.ToString();
            this.txtbxTrackedFeatures.Text = currentNavigationOption.TrackedFeaturesCount.ToString();
            this.txtbxNotTrackedFeatures.Text = currentNavigationOption.NotTrackedFeaturesCount.ToString();
            this.txtbxLeftSum.Text = Math.Round(((double)currentNavigationOption.OpticalFlowStoreData.left.sumGroundCountX / (double)currentNavigationOption.OpticalFlowStoreData.left.groundCount), 4).ToString();
            this.txtbxRightSum.Text = Math.Round(((double)currentNavigationOption.OpticalFlowStoreData.right.sumGroundCountX / (double)currentNavigationOption.OpticalFlowStoreData.right.groundCount), 4).ToString();
            this.txtbxCenterSum.Text = Math.Round(currentNavigationOption.OpticalFlowStoreData.totalCollisionTime, 4).ToString();
            this.txtbxSonar.Text = (!string.IsNullOrEmpty(currentNavigationOption.CurrentCollisionHistogram.SonarCollisionDistance)) ? currentNavigationOption.CurrentCollisionHistogram.SonarCollisionDistance : string.Empty;

            if (currentNavigationOption.HasFound)
            {
                this.btnCollision.Background = System.Windows.Media.Brushes.Red;
            }
            else
            {
                this.btnCollision.Background = collisionButtonBackground;
            }
        }

        private void WindowLoaded(object sender, RoutedEventArgs e)
        {
            this.timer = new DispatcherTimer();
            this.timer.Tick += new EventHandler(timer_Tick);
            this.timer.Interval = new TimeSpan(0, 0, 0, 0, 1);
            this.timer.Start();
        }

        private void wndoiNavigate_Closing(object sender, CancelEventArgs e)
        {
            // dispose both navigator objects
            this.topNavigator.Dispose();
            this.bottomnavigator.Dispose();
        }

        private void workerProcess_DoWork(object sender, DoWorkEventArgs e)
        {
            this.bottomnavigator.DiagnoseDevice(EnumUtil.ParseEnum<Device>(this.selectedItem));
        }

        private void workerProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.rdbsyIndicator.IsBusy = false;
        }
    }
}